package com.xaicode.learn.netty.websocket;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;

/**
 * @author Locker xaicode@sina.com
 * @version 1.0
 * @date 2021/6/19 0019 21:59
 */
public class WebsocketServer {

    public static void main(String[] args) {

        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap
                    .group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();

                            // add http codec
                            pipeline.addLast(new HttpServerCodec());

                            /*
                                A ChannelHandler that adds support for writing a large data stream asynchronously
                                neither spending a lot of memory nor getting OutOfMemoryError.
                             */
                            pipeline.addLast(new ChunkedWriteHandler());

                            /*
                                A ChannelHandler that aggregates an HttpMessage and its following HttpContents
                                into a single FullHttpRequest or FullHttpResponse (depending on if it used to handle
                                requests or responses) with no following HttpContents.
                             */
                            pipeline.addLast(new HttpObjectAggregator(8192));

                            /*
                                This handler does all the heavy lifting for you to run a websocket server.
                                Browser request url [ws://localhost:7777/hello].
                                Http upgrade to WS with http code 101.
                             */
                            pipeline.addLast(new WebSocketServerProtocolHandler("/hello"));

                            // self handler
                            pipeline.addLast(new WSTextWebSocketFrameHandler());
                        }
                    });

            ChannelFuture channelFuture = serverBootstrap.bind(7777).sync();

            channelFuture.channel().closeFuture().sync();

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}
